Link to this headingAssembly

Intro to RE

Code and compiled assembly back to back

Tutorials:
ASCII table
x86_64 NASM Assembly Quick Reference
x86 Architecture Overview
ARM Assembly to HEX
Intel Introduction to x64 Assembly
x86 and amd64 instruction reference
ARM Assembly Basics

Link to this headingBasics

Stack operations:

  • push value: pushes a value into the stack (decrements ESP by 4, the size of one stack ‘unit’).
  • pop register: pops a value to a register (increments ESP by 4).

Data transfer:

  • mov destination, source: moves copies a value from/to a register.
  • mov destination, [expression]: copies a value from a memory address resolved from a ‘register expression’ (single register or arithmetic expression involving one or more registers) into a register.

Flow control:

  • jmp destination: jumps into a code location (sets EIP (instruction pointer)).
  • jz/je destination: jumps into a code location if ZF (the zero flag) is set.
  • jnz/jne destination: jumps into a code location if ZF is not set.

Operations:

  • cmp operand1, operand2: compares the 2 operands and sets ZF if they’re equal.
  • add operand1, operand2: operand1 += operand2;
  • sub operand1, operand2: operand1 -= operand2;

Function transitions:

  • call function: calls a function (pushes current EIP, then jumps to the function).
  • retn: returns to caller function (pops back the previous EIP).

Link to this headingFunctions

Function prologue:
A function prologue is some initial code embedded in the beginning of most functions, it serves to set up a new stack frame for said function.

55 push ebp ; preserve caller function's base pointer in stack 8B EC mov ebp, esp ; caller function's stack pointer becomes base pointer (new stack frame) 83 EC XX sub esp, X ; adjust the stack pointer by X bytes to reserve space for local variables

Function epilogue:*
The epilogue is simply the opposite of the prologue - it undoes its steps to restore the stack frame of the caller function, before it returns to it:

8B E5 mov esp, ebp ; restore caller function's stack pointer (current base pointer) 5D pop ebp ; restore base pointer from the stack C3 retn ; return to caller function

Now at this point, you might be wondering - how do functions talk to each other? How exactly do you send/access arguments when calling a function, and how do you receive the return value? That’s precisely why we have calling conventions.

Link to this headingCalling conventions

__cdecl:

;func(1, 2, 3); 6A 03 push 3 6A 02 push 2 6A 01 push 1 E8 XX XX XX XX call func

Link to this headingPutting it together

int __cdecl func(int, int, int): prologue: 55 push ebp ; save base pointer 8B EC mov ebp, esp ; new stack frame body: 8B 45 08 mov eax, [ebp+8] ; load first argument to EAX (return value) 03 45 0C add eax, [ebp+0Ch] ; add 2nd argument 03 45 10 add eax, [ebp+10h] ; add 3rd argument epilogue: 5D pop ebp ; restore base pointer C3 retn ; return to caller